﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

using System.Configuration;
using ESF.MUP.BasePlatform.Configuration;

using ESF.MUP.BasePlatform.ApplicationServices.Interfaces;
using ESF.MUP.BasePlatform.Services;
using ESF.MUP.BasePlatform.Domain.Repositories;
using ESF.MUP.BasePlatform.DbRepositories;
using ESF.MUP.BasePlatform.DbRepository.MSSQL;

namespace ESF.MUP.BasePlatform
{
    public class MiddlewareManagementService
    {

        #region "private members"
        /// <summary>
        /// Unity container to register and resolve platform manager type
        /// </summary>
        private Microsoft.Practices.Unity.UnityContainer _container = new UnityContainer();

        /// <summary>
        /// Singleton
        /// </summary>
        private static MiddlewareManagementService _managementService = new MiddlewareManagementService();



        #endregion

        public String ConfigurationFile { get; private set; }
        public String ConnectorsPath { get; private set; }

        public List<ConnectorConfiguration> Connectors = new List<ConnectorConfiguration>();

        /// <summary>
        /// Constructor
        /// </summary>
        private MiddlewareManagementService()
        {
            this.ConnectorsPath = @"D:\Temp\Connectors";
            this.ConfigurationFile = @"D:\Tools\MESF\Main\MiddlewareManager\ESF.MUP.BasePlatform\bin\Debug\ESF.MUP.BasePlatform.dll.config";


            System.AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler((o, asmargs) =>
            { 
                switch(asmargs.Name)
                {
                    case "ESF.MUP.BasePlatform.DbRepositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null":
                        String asmDbservice = @"D:\Tools\MESF\Main\DataAccessLayer\ESF.MUP.BasePlatform.DbRepositories\bin\Debug\ESF.MUP.BasePlatform.DbRepositories.dll";
                        return System.Reflection.Assembly.LoadFrom(asmDbservice);
                    case "ESF.MUP.BasePlatform.DbRepository.MSSQL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null":
                        String asmDbserviceMSQL = @"D:\Tools\MESF\Main\DataAccessLayer\ESF.MUP.BasePlatform.DbRepository.MSSQL\bin\Debug\ESF.MUP.BasePlatform.DbRepository.MSSQL.dll";
                        return System.Reflection.Assembly.LoadFrom(asmDbserviceMSQL);
                    default:
                        return System.Reflection.Assembly.LoadFrom(asmargs.Name + ".dll");
                }
            });


            this.Init();
            this.LoadUnityManually();
        }

        public static MiddlewareManagementService Current
        { get { return _managementService; } }

        /// <summary>
        /// Init the MUP platform by browsing its connectors folder
        /// </summary>
        public void Init()
        {

            //Retrieve the list of connectors folder
            String[] connectorDirectories = System.IO.Directory.GetDirectories(this.ConnectorsPath);
            foreach (String connectorDirectory in connectorDirectories)
            {
                ConnectorConfiguration connector = new ConnectorConfiguration(connectorDirectory);
                this.Connectors.Add(connector);

                if (connector.Status == ConnectorStatus.TypeResolved)
                {
                    _container.RegisterType(typeof(PlatformManager), connector.ManagerType, connector.Name);
                }

            }
        }


        /// <summary>
        /// Add a new manager to the MUP
        /// </summary>
        /// <returns></returns>
        public Boolean AddManager(string managerName, String packagedManagerModulePath)
        {
            //Unpack the packaged manager module 
            this.UnpackManagerModule(managerName, packagedManagerModulePath);

            //Discover the new manager
            String connectorDirectoryPath = System.IO.Path.Combine(this.ConnectorsPath, managerName);
            ConnectorConfiguration connector = new ConnectorConfiguration(connectorDirectoryPath);
            this.Connectors.Add(connector);

            if (connector.Status == ConnectorStatus.TypeResolved)
            {
                _container.RegisterType(typeof(PlatformManager), connector.ManagerType, connector.Name);
            }

            return true;

        }

        public void UnpackManagerModule(string managerName, String packagedManagerModulePath)
        {

        }


        /// <summary>
        /// Get a manager for a platform according its name
        /// </summary>
        public PlatformManager GetManager(String name)
        {
            return _container.Resolve<PlatformManager>(name);
        }


        /// <summary>
        /// Load the IOC configuration from unity
        /// </summary>
        /// <param name="configurationFilePath"></param>
        public void LoadBaseConfiguration(String configurationFilePath)
        {
            var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configurationFilePath };
            System.Configuration.Configuration configuration =
                ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            var unitySection = (UnityConfigurationSection)configuration.GetSection("unity");

            _container.LoadConfiguration(unitySection);
        }

        public void LoadUnityManually()
        {
            System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection(@"data source=.\ESF;initial catalog=ESF_MUP;integrated security=True");
            _container.RegisterType<UnitOfWork,SqlContext>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager(),
                                               new InjectionConstructor(cn));

            _container.RegisterType<IApplicationRepository, ApplicationRepository>();
            _container.RegisterType<IEnvironmentRepository, EnvironmentRepository>();

            _container.RegisterType<IApplicationManagementService, ApplicationManagementService>();
            _container.RegisterType<IEnvironmentManagementService, EnvironmentManagementService>();

        }

        public IApplicationManagementService GetApplicationService()
        {
            //_container.Resolve<System.Data.Common.DbConnection>();
            //_container.Resolve<IRepository<ESF.MUP.CoreInfrastructure.Model.Application>>();
            return _container.Resolve<IApplicationManagementService>(); 
        }

        public IEnvironmentManagementService GetEnvironmentService()
        {
            //_container.Resolve<System.Data.Common.DbConnection>();
            //_container.Resolve<IRepository<ESF.MUP.CoreInfrastructure.Model.Application>>();
            return _container.Resolve<IEnvironmentManagementService>();
            //return new ESF.MUP.BasePlatform.Services.EnvironmentManagementService(
        }

    }
}
